/************************************************************
   Copyright 2008 Abhinav Pobbati

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*************************************************************/

#include "HkPrerequisites.h"

#include "Havok4Xna/Physics/Dynamics/World/HkpWorld.h"
#include "Havok4Xna/Physics/Dynamics/World/Listener/HkpListener.h"
#include "Havok4Xna/Physics/Dynamics/World/BroadPhaseBorder/HkpBroadPhaseBorder.h"
#include "Havok4Xna/Physics/Dynamics/Action/HkpAction.h"
#include "Havok4Xna/Physics/Dynamics/Collide/HkpCollide.h"
#include "Havok4Xna/Physics/Dynamics/Constraint/HkpConstraint.h"
#include "Havok4Xna/Physics/Dynamics/Common/HkpCommon.h"
#include "Havok4Xna/Physics/Dynamics/Phantom/HkpPhantom.h"
#include "Havok4Xna/Physics/Dynamics/Entity/HkpEntity.h"
#include "Havok4Xna/Physics/Collide/Query/HkpQuery.h"
#include "Havok4Xna/Physics/Collide/Agent/HkpAgent.h"
#include "Havok4Xna/Physics/ConstraintSolver/HkpConstraintSolver.h"
#include "Havok4Xna/Physics/Collide/Filter/HkpFilter.h"
#include "Havok4Xna/Physics/Internal/HkpInternal.h"
#include "Havok4Xna/Common/Base/Math/HkVector4.h"
#include "Havok4Xna/Common/Base/Types/HkAabb.h"
#include "Havok4Xna/Common/Base/Types/HkStepInfo.h"

using System::Runtime::InteropServices::Marshal;

namespace Havok4Xna {
	namespace Physics {
		namespace Dynamics {
			void HkWorldMemoryAvailableWatchDog::WatchMemory(HkpWorld ^world) {
				_this()->watchMemory(world->_this());
			}
			void HkWorldMemoryAvailableWatchDog::FreeMemory(HkpWorld ^world) {
				_this()->freeMemory(world->_this());
			}

			HkpDefaultWorldMemoryWatchDog::HkpDefaultWorldMemoryWatchDog()
				: HkWorldMemoryAvailableWatchDog(new hkpDefaultWorldMemoryWatchDog(), true) {
			}
			HkpDefaultWorldMemoryWatchDog::HkpDefaultWorldMemoryWatchDog(int minMemoryAvailable)
				: HkWorldMemoryAvailableWatchDog(new hkpDefaultWorldMemoryWatchDog(minMemoryAvailable), true) {
			}


			
			void HkpWorldObject::AddProperty(hkUint32 key, HkpPropertyValue ^value) {
				if(_properties == nullptr)
					_properties = gcnew Dictionary<hkUint32, HkpPropertyValue^>();
				_properties[key] = value;
				_ref().addProperty(key, value->_ref());
			}
			HkpPropertyValue ^HkpWorldObject::RemoveProperty(hkUint32 key) {
				if(_properties == nullptr)
					_properties = gcnew Dictionary<hkUint32, HkpPropertyValue^>();

				_ref().removeProperty(key);
				HkpPropertyValue ^val = nullptr;
				if(_properties->ContainsKey(key)) {
					val = _properties[key];
					_properties->Remove(key);
				}
				return val;
			}
			void HkpWorldObject::EditProperty(hkUint32 key, HkpPropertyValue ^value) {
				_ref().editProperty(key, value->_ref());
			}
			HkpPropertyValue ^HkpWorldObject::GetProperty(hkUint32 key) {
				if(_properties == nullptr)
					_properties = gcnew Dictionary<hkUint32, HkpPropertyValue^>();
				return _properties[key];
			}
			bool HkpWorldObject::HasProperty(hkUint32 key) {
				return _ref().hasProperty(key);
			}
			void HkpWorldObject::LockProperty(hkUint32 key) {
				_ref().lockProperty(key);
			}
			void HkpWorldObject::UnlockPropety(hkUint32 key) {
				_ref().unlockProperty(key);
			}
			void HkpWorldObject::UnlockPropertiesFromLoadedObject() {
				_ref().unlockPropertiesFromLoadedObject();
			}
			void HkpWorldObject::ClearAndDeallocateProperties() {
				_ref().clearAndDeallocateProperties();
			}
			HkWorldOperationResult HkpWorldObject::SetShape(HkpShape ^shape) {
				return (HkWorldOperationResult) _ref().setShape((hkpShape*) shape->GetNativePointer());
			}
			void HkpWorldObject::CopyProperties(HkpWorldObject ^obj) {
				_ref().copyProperties(obj->_this());
			}
			String ^HkpWorldObject::Name::get() {
				return gcnew String(_ref().getName());
			}
			void HkpWorldObject::Name::set(String ^name) {
				ALLOC_StringToCStr_ANSI(tmp, name);
				_ref().setName(tmp);
				Marshal::FreeHGlobal(IntPtr((void*) tmp));
			}

			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorldObject, Collidable, HkpCollidable,
				hkpWorldObject, getCollidable, hkpCollidable);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorldObject, CollidableRw, HkpCollidable,
				hkpWorldObject, getCollidableRw, hkpCollidable);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorldObject, LinkedCollidable, HkpLinkedCollidable,
				hkpWorldObject, getLinkedCollidable, hkpLinkedCollidable);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorldObject, World, HkpWorld,
				hkpWorldObject, getWorld, hkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, IsAddedToWorld, isAddedToWorld, HkpWorldObject);
			IMPL_SIMPLE_PROPERTY_GETTERSETTER(hkUlong, UserData, getUserData, setUserData, HkpWorldObject);



			HkpWorld::HkpWorld(HkpWorldCinfo ^info) {
				_setThis(new hkpWorld(info->_ref()), true);
				_Cinfo = info;
			}
			void HkpWorld::AddEntity(HkpEntity ^entity) {
				_ref().addEntity(entity->_this());
			}
			void HkpWorld::AddEntity(HkpEntity ^entity, HkpEntityActivation initialActivationState) {
				_ref().addEntity(entity->_this(), (hkpEntityActivation) initialActivationState);
			}
			bool HkpWorld::RemoveEntity(HkpEntity ^entity) {
				return _ref().removeEntity(entity->_this());
			}
			HkpConstraintInstance ^HkpWorld::AddConstraint(HkpConstraintInstance ^constraint) {
				_ref().addConstraint(constraint->_this());
				return constraint;
			}
			bool HkpWorld::RemoveConstraint(HkpConstraintInstance ^constraint) {
				return _ref().removeConstraint(constraint->_this());
			}
			HkpConstraintInstance ^HkpWorld::CreateAndAddConstraintInstance(HkpRigidBody ^bodyA, HkpRigidBody ^bodyB, HkpConstraintData ^constraintData) {
				return gcnew HkpConstraintInstance(_ref().createAndAddConstraintInstance(bodyA->_this(), bodyB->_this(), constraintData->_this()), true);
			}
			HkpAction ^HkpWorld::AddAction(HkpAction ^action) {
				_ref().addAction(action->_this());
				return action;
			}
			void HkpWorld::RemoveAction(HkpAction ^action) {
				_ref().removeAction(action->_this());
			}
			void HkpWorld::RemoveActionImmediately(HkpAction ^action) {
				_ref().removeActionImmediately(action->_this());
			}
			HkpPhantom ^HkpWorld::AddPhantom(HkpPhantom ^phantom) {
				_ref().addPhantom(phantom->_this());
				return phantom;
			}
			void HkpWorld::RemovePhantom(HkpPhantom ^phantom) {
				_ref().removePhantom(phantom->_this());
			}
			void HkpWorld::ActivateRegion(HkAabb ^box) {
				_ref().activateRegion(box->_ref());
			}
			void HkpWorld::AddPhysicsSystem(HkpPhysicsSystem ^system) {
				_ref().addPhysicsSystem(system->_this());
			}
			void HkpWorld::RemovePhysicsSystem(HkpPhysicsSystem ^system) {
				_ref().removePhysicsSystem(system->_this());
			}
			void HkpWorld::UpdateCollisionFilterOnEntity(HkpEntity ^entity, HkpUpdateCollisionFilterOnEntityMode updateMode, HkpUpdateCollectionFilterMode updateShapeCollectionFilter) {
				_ref().updateCollisionFilterOnEntity(entity->_this(), (hkpUpdateCollisionFilterOnEntityMode) updateMode, (hkpUpdateCollectionFilterMode) updateShapeCollectionFilter);
			}
			void HkpWorld::UpdateCollisionFilterOnPhantom(HkpPhantom ^phantom, HkpUpdateCollectionFilterMode updateShapeCollectionFilter) {
				_ref().updateCollisionFilterOnPhantom(phantom->_this(), (hkpUpdateCollectionFilterMode) updateShapeCollectionFilter);
			}
			void HkpWorld::UpdateCollsionFilterOnWorld(HkpUpdateCollisionFilterOnWorldMode updateMode, HkpUpdateCollectionFilterMode updateShapeCollectionFilter) {
				_ref().updateCollisionFilterOnWorld((hkpUpdateCollisionFilterOnWorldMode) updateMode, (hkpUpdateCollectionFilterMode) updateShapeCollectionFilter);
			}
			void HkpWorld::ReintegrateAndRecollideEntities(IEnumerable<HkpEntity^> ^entityBatch, ReintegrationRecollideMode mode) {
				// TODO:
			}
			void HkpWorld::ReintegrateAndRecollideEntities(IEnumerable<HkpEntity^> ^entityBatch) {
				// TODO:
			}
			void HkpWorld::FindInitialContactPoints(IEnumerable<HkpEntity^>^ entities) {
				// TODO:
			}
			void HkpWorld::FindInitialContactPointsOfAllEntities() {
				_ref().findInitialContactPointsOfAllEntities();
			}
			void HkpWorld::CheckDeterminism() {
				_ref().checkDeterminism();
			}
			void HkpWorld::Lock() {
				_ref().lock();
			}
			void HkpWorld::LockReadOnly() {
				_ref().lockReadOnly();
			}
			void HkpWorld::Unlock() {
				_ref().unlock();
			}
			void HkpWorld::UnlockReadOnly() {
				_ref().unlockReadOnly();
			}
			void HkpWorld::MarkForRead() {
				_ref().markForRead();
			}
			void HkpWorld::MarkForWrite() {
				_ref().markForWrite();
			}
			void HkpWorld::UnmarkForRead() {
				_ref().unmarkForRead();
			}
			void HkpWorld::UnmarkForWrite() {
				_ref().unmarkForWrite();
			}
			void HkpWorld::AddActionListener(HkpActionListener ^worldListener) {
				_ref().addActionListener(worldListener->_this());
			}
			void HkpWorld::RemoveActionListener(HkpActionListener ^worldListener) {
				_ref().removeActionListener(worldListener->_this());
			}
			void HkpWorld::AddConstraintListener(HkpConstraintListener ^worldListener) {
				_ref().addConstraintListener(worldListener->_this());
			}
			void HkpWorld::RemoveConstraintListener(HkpConstraintListener ^worldListener) {
				_ref().removeConstraintListener(worldListener->_this());
			}
			void HkpWorld::AddEntityListener(HkpEntityListener ^worldListener) {
				_ref().addEntityListener(worldListener->_this());
			}
			void HkpWorld::RemoveEntityListener(HkpEntityListener ^worldListener) {
				_ref().removeEntityListener(worldListener->_this());
			}
			void HkpWorld::AddPhantomListener(HkpPhantomListener ^worldListener) {
				_ref().addPhantomListener((hkpPhantomListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemovePhantomListener(HkpPhantomListener ^worldListener) {
				_ref().removePhantomListener((hkpPhantomListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddIslandActivationListener(HkpIslandActivationListener ^worldListener) {
				_ref().addIslandActivationListener((hkpIslandActivationListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveIslandActivationListener(HkpIslandActivationListener ^worldListener) {
				_ref().removeIslandActivationListener((hkpIslandActivationListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddWorldPostCollideListener(HkpWorldPostCollideListener ^worldListener) {
				_ref().addWorldPostCollideListener((hkpWorldPostCollideListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveWorldPostCollideListener(HkpWorldPostCollideListener ^worldListener) {
				_ref().removeWorldPostCollideListener((hkpWorldPostCollideListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddWorldPostSimulationListener(HkpWorldPostSimulationListener ^worldListener) {
				_ref().addWorldPostSimulationListener((hkpWorldPostSimulationListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveWorldPostSimulationListener(HkpWorldPostSimulationListener ^worldListener) {
				_ref().removeWorldPostSimulationListener((hkpWorldPostSimulationListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddWorldPostIntegrateListener(HkpWorldPostIntegrateListener ^worldListener) {
				_ref().addWorldPostIntegrateListener((hkpWorldPostIntegrateListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveWorldPostIntegrateListener(HkpWorldPostIntegrateListener ^worldListener) {
				_ref().removeWorldPostIntegrateListener((hkpWorldPostIntegrateListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddIslandPostCollideListener(HkpIslandPostCollideListener ^islandListener) {
				_ref().addIslandPostCollideListener((hkpIslandPostCollideListener*) islandListener->GetNativePointer());
			}
			void HkpWorld::RemoveIslandPostCollideListener(HkpIslandPostCollideListener ^islandListener) {
				_ref().removeIslandPostCollideListener((hkpIslandPostCollideListener*) islandListener->GetNativePointer());
			}
			void HkpWorld::AddIslandPostIntegrateListener(HkpIslandPostIntegrateListener ^islandListener) {
				_ref().addIslandPostIntegrateListener((hkpIslandPostIntegrateListener*) islandListener->GetNativePointer());
			}
			void HkpWorld::RemoveIslandPostIntegrateListener(HkpIslandPostIntegrateListener ^islandListener) {
				_ref().removeIslandPostIntegrateListener((hkpIslandPostIntegrateListener*) islandListener->GetNativePointer());
			}
			void HkpWorld::AddCollisionListener(HkpCollisionListener ^worldListener) {
				_ref().addCollisionListener((hkpCollisionListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveCollisionListener(HkpCollisionListener ^worldListener) {
				_ref().removeCollisionListener((hkpCollisionListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddWorldDeletionListener(HkpWorldDeletionListener ^worldListener) {
				_ref().addWorldDeletionListener((hkpWorldDeletionListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::RemoveWorldDeletionListener(HkpWorldDeletionListener ^worldListener) {
				_ref().removeWorldDeletionListener((hkpWorldDeletionListener*) worldListener->GetNativePointer());
			}
			void HkpWorld::AddContactImpulseLimitBreachedListener(HkpContactImpulseLimitBreachedListener ^listener) {
				_ref().addContactImpulseLimitBreachedListener((hkpContactImpulseLimitBreachedListener*) listener->GetNativePointer());
			}
			void HkpWorld::RemoveContactImpulseLimitBreachedListener(HkpContactImpulseLimitBreachedListener ^listener) {
				_ref().removeContactImpulseLimitBreachedListener((hkpContactImpulseLimitBreachedListener*) listener->GetNativePointer());
			}
			void HkpWorld::SetCollisionFilter(HkpCollisionFilter ^filter, bool runUpdateCollisionFilterOnWorld,
				HkpUpdateCollisionFilterOnWorldMode checkBroadPhaseMode,
				HkpUpdateCollectionFilterMode updateShapeCollectionFilter) {
				_ref().setCollisionFilter(filter->_this(), runUpdateCollisionFilterOnWorld,
					(hkpUpdateCollisionFilterOnWorldMode) checkBroadPhaseMode,
					(hkpUpdateCollectionFilterMode) updateShapeCollectionFilter);
			}
			void HkpWorld::CastRay(HkpWorldRayCastInput ^input, HkpWorldRayCastOutput ^output) {
				_ref().castRay(input->_ref(), output->_ref());
			}
			void HkpWorld::CastRay(HkpWorldRayCastInput ^input, HkpRayHitCollector ^collector) {
				_ref().castRay(input->_ref(), collector->_ref());
			}
			void HkpWorld::LinearCast(HkpCollidable ^collA, HkpLinearCastInput ^input, HkpCdPointCollector ^castCollector,
				HkpCdPointCollector ^startCollector) {
				_ref().linearCast(collA->_this(), input->_ref(), castCollector->_ref(), startCollector->_this());
			}
			void HkpWorld::LinearCast(HkpCollidable ^collA, HkpLinearCastInput ^input, HkpCdPointCollector ^castCollector) {
				_ref().linearCast(collA->_this(), input->_ref(), castCollector->_ref());
			}
			void HkpWorld::GetClosestPoints(HkpCollidable ^collA, HkpCollisionInput ^input, HkpCdPointCollector ^collector) {
				_ref().getClosestPoints(collA->_this(), input->_ref(), collector->_ref());
			}
			void HkpWorld::GetPenetrations(HkpCollidable ^collA, HkpCollisionInput ^input, HkpCdBodyPairCollector ^collector) {
				_ref().getPenetrations(collA->_this(), input->_ref(), collector->_ref());
			}
			void HkpWorld::ShiftBroadPhase(HkVector4 ^shiftDistance, [Out] HkVector4 ^effectShiftDistanceOut,
				IEnumerable<HkpBroadPhaseHandle^> ^objectsEnteringBroadphaseBorder) {
				// TODO:
			}
			HkpStepResult HkpWorld::StepDeltaTime(float physicsDeltaTime) {
				return (HkpStepResult) _ref().stepDeltaTime(physicsDeltaTime);
			}
			HkpStepResult HkpWorld::Integrate(float physicsDeltaTime) {
				return (HkpStepResult) _ref().integrate(physicsDeltaTime);
			}
			HkpStepResult HkpWorld::Collide() {
				return (HkpStepResult) _ref().collide();
			}
			HkpStepResult HkpWorld::AdvanceTime() {
				return (HkpStepResult) _ref().advanceTime();
			}
			void HkpWorld::ResetThreadTokens() {
				_ref().resetThreadTokens();
			}
			void HkpWorld::CheckAccessGetActiveSimulationIslands() {
				_ref().checkAccessGetActiveSimulationIslands();
			}
			void HkpWorld::AttachActionToEntity(HkpAction ^action, HkpEntity ^entity) {
				_ref().attachActionToEntity(action->_this(), entity->_this());
			}
			void HkpWorld::DetachActionFromEntity(HkpAction ^action, HkpEntity ^entity) {
				_ref().detachActionFromEntity(action->_this(), entity->_this());
			}

			HkpWorldCinfo ^HkpWorld::Cinfo::get() {
				return _Cinfo;
			}
			HkWorldMemoryAvailableWatchDog ^HkpWorld::MemoryWatchDog::get() {
				return _Cinfo->MemoryWatchDog;
			}
			HkpThreadToken HkpWorld::ThreadToken::get() {
				return (HkpThreadToken) _ref().getThreadToken();
			}
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, FixedRigidBody, HkpRigidBody,
				hkpWorld, getFixedRigidBody, hkpRigidBody);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, BroadPhase, HkpBroadPhase,
				hkpWorld, getBroadPhase, hkpBroadPhase);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, CollisionInput, HkpProcessCollisionInput,
				hkpWorld, getCollisionInput, hkpProcessCollisionInput);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, CollisionDispatcher, HkpCollisionDispatcher,
				hkpWorld, getCollisionDispatcher, hkpCollisionDispatcher);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, CollisionFilter, HkpCollisionFilter,
				hkpWorld, getCollisionFilter, hkpCollisionFilter);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, FixedIsland, HkpSimulationIsland,
				hkpWorld, getFixedIsland, hkpSimulationIsland);
			IMPL_COMPLEX_PROPERTY_GETTER_2(
				HkpWorld, WorldAsOneSystem, HkpPhysicsSystem,
				hkpWorld, getWorldAsOneSystem, hkpPhysicsSystem);
			IMPL_COMPLEX_PROPERTY_GETTERSETTER_2(
				HkpWorld, BroadPhaseBorder, HkpBroadPhaseBorder,
				hkpWorld, getBroadPhaseBorder, setBroadPhaseBorder, hkpBroadPhaseBorder);
			IMPL_SIMPLE_PROPERTY_SETTER(float, FrameTimeMarker, setFrameTimeMarker, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(int, MemUsageForIntegration, getMemUsageForIntegration, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, IsLocked, isLocked, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, IsSimulationAtMarker, isSimulationAtMarker, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, IsSimulationAtPsi, isSimulationAtPsi, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(float, CurrentTime, getCurrentTime, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETTER(float, CurrentPsiTime, getCurrentPsiTime, HkpWorld);
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ProcessActionsInSingleThread, m_processActionsInSingleThread, HkpWorld);



			HkpWorldCinfo::HkpWorldCinfo() {
				_setThis(new hkpWorldCinfo(), true);
			}
			void HkpWorldCinfo::SetupSolverInfo(HkpWorldCinfo::SolverType st) {
				_this()->setupSolverInfo((hkpWorldCinfo::SolverType) st);
			}
			void HkpWorldCinfo::SetBroadPhaseWorldSize(float size) {
				_this()->setBroadPhaseWorldSize(size);
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpWorldCinfo, Gravity, HkVector4,
				hkpWorldCinfo, m_gravity, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET_2(
				HkpWorldCinfo, MemoryWatchDog, HkWorldMemoryAvailableWatchDog,
				hkpWorldCinfo, m_memoryWatchDog, hkWorldMemoryAvailableWatchDog);
			IMPL_COMPLEX_PROPERTY_GETSET_2(
				HkpWorldCinfo, CollisionFilter, HkpCollisionFilter,
				hkpWorldCinfo, m_collisionFilter, hkpCollisionFilter);
			IMPL_COMPLEX_PROPERTY_GET(
				HkpWorldCinfo, BroadPhaseWorldAabb, HkAabb,
				hkpWorldCinfo, m_broadPhaseWorldAabb, hkAabb);
			#pragma unmanaged
			static inline void set_BroadPhaseWorldAabb(hkpWorldCinfo *w, hkAabb &b) {
				w->m_broadPhaseWorldAabb = b;
			}
			#pragma managed
			void HkpWorldCinfo::BroadPhaseWorldAabb::set(HkAabb ^value) {
				set_BroadPhaseWorldAabb(_this(), value->_ref());
			}
			HkpConvexListFilter ^HkpWorldCinfo::ConvexListFilter::get() { return _ConvexListFilter; }
			void HkpWorldCinfo::ConvexListFilter::set(HkpConvexListFilter ^v) {
				_ConvexListFilter = v;
				_ref().m_convexListFilter = v == nullptr ? nullptr : (hkpConvexListFilter*) v->GetNativePointer();
			}
			IMPL_SIMPLE_PROPERTY_GETSET(int, BroadPhaseQuerySize, m_broadPhaseQuerySize, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, ContactRestingVelocity, m_contactRestingVelocity, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, CollisionTolerance, m_collisionTolerance, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, ExpectedMaxLinearVelocity, m_expectedMaxLinearVelocity, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, SizeOfToiEventQueue, m_sizeOfToiEventQueue, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, ExpectedMinPsiDeltaTime, m_expectedMinPsiDeltaTime, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, BroadPhaseNumMarkers, m_broadPhaseNumMarkers, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, SolverTau, m_solverTau, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, SolverDamp, m_solverDamp, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, SolverIterations, m_solverIterations, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, SolverMicrosteps, m_solverMicrosteps, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ForceCoherentConstraintOrderingInSolver, m_forceCoherentConstraintOrderingInSolver, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, SnapCollisionToConvexEdgeThreshold, m_snapCollisionToConvexEdgeThreshold, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, EnableToiWeldRejection, m_enableToiWeldRejection, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, EnabledDeprecatedWelding, m_enableDeprecatedWelding, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, IterativeLinearCastEarlyOutDistance, m_iterativeLinearCastEarlyOutDistance, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, IterativeLinearCastMaxIterations, m_iterativeLinearCastMaxIterations, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, HighFrequencyDeactivationPeriod, m_highFrequencyDeactivationPeriod, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, LowFrequencyDeactivationPeriod, m_lowFrequencyDeactivationPeriod, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(Byte, DeactivationNumInactiveFramesSelectFlag0, m_deactivationNumInactiveFramesSelectFlag0, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(Byte, DeactivationNumInactiveFramesSelectFlag1, m_deactivationNumInactiveFramesSelectFlag1, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(Byte, DeactivationIntegrateCounter, m_deactivationIntegrateCounter, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ShouldActivateOnRigidBodyTransformChange, m_shouldActivateOnRigidBodyTransformChange, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, DeactivationReferenceDistance, m_deactivationReferenceDistance, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, ToiCollisionResponseRotateNormal, m_toiCollisionResponseRotateNormal, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, MaxSectorsPerCollideTask, m_maxSectorsPerCollideTask, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ProcessToisMultithreaded, m_processToisMultithreaded, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(int, MaxEntriesPerToiCollideTask, m_maxEntriesPerToiCollideTask, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, EnableDeactivation, m_enableDeactivation, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, EnableSimulationIslands, m_enableSimulationIslands, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(UInt32, MinDesiredIslandSize, m_minDesiredIslandSize, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ProcessActionsInSingleThread, m_processActionsInSingleThread, HkpWorldCinfo)
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrameMarkerPsiSnap, m_frameMarkerPsiSnap, HkpWorldCinfo)


			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpWorldDynamicsStepInfo, StepInfo, HkStepInfo,
				hkpWorldDynamicsStepInfo, m_stepInfo, hkStepInfo);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpWorldDynamicsStepInfo, SolverInfo, HkpSolverInfo,
				hkpWorldDynamicsStepInfo, m_solverInfo, hkpSolverInfo);


			HkpPhysicsSystem::HkpPhysicsSystem() {
				_setThis(new hkpPhysicsSystem(), true);
			}
			void HkpPhysicsSystem::AddRigidBody(HkpRigidBody ^body) {
				_ref().addRigidBody(body->_this());
			}
			void HkpPhysicsSystem::AddPhantom(HkpPhantom ^phantom) {
				_ref().addPhantom(phantom->_this());
			}
			void HkpPhysicsSystem::AddConstraint(HkpConstraintInstance ^constraint) {
				_ref().addConstraint(constraint->_this());
			}
			void HkpPhysicsSystem::AddAction(HkpAction ^action) {
				_ref().addAction(action->_this());
			}
			void HkpPhysicsSystem::RemoveRigidBody(int i) {
				_ref().removeRigidBody(i);
			}
			void HkpPhysicsSystem::RemovePhantom(int i) {
				_ref().removePhantom(i);
			}
			void HkpPhysicsSystem::RemoveConstraint(int i) {
				_ref().removeConstraint(i);
			}
			void HkpPhysicsSystem::RemoveAction(int i) {
				_ref().removeAction(i);
			}
			String ^HkpPhysicsSystem::Name::get() {
				return gcnew String(_ref().getName());
			}
			void HkpPhysicsSystem::Name::set(String ^name) {
				ALLOC_StringToCStr_ANSI(tmp, name);
				_ref().setName(tmp);
				Marshal::FreeHGlobal(IntPtr((void*) tmp));
			}
			IMPL_SIMPLE_PROPERTY_GETTERSETTER(hkUlong, UserData, getUserData, setUserData, HkpPhysicsSystem);
			IMPL_SIMPLE_PROPERTY_GETTERSETTER(bool, Active, isActive, setActive, HkpPhysicsSystem);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, HasContacts, hasContacts, HkpPhysicsSystem);
			/*DECLARE_PROPERTY_GET(HkArray<HkpRigidBody^>, RigidBodies);
			DECLARE_PROPERTY_GET(HkArray<HkpPhantom^>, Phantoms);
			DECLARE_PROPERTY_GET(HkArray<HkpConstraintInstance^>, Constraints);
			DECLARE_PROPERTY_GET(HkArray<HkpAction^>, Actions);*/



			IMPL_SIMPLE_PROPERTY_GETTER(bool, WasActiveLastFrame, wasActiveLastFrame, HkpSimulationIsland);
			IMPL_SIMPLE_PROPERTY_GETTER(bool, IsFixed, isFixed, HkpSimulationIsland);
			HkpWorld ^HkpSimulationIsland::World::get() { return world; }
			IMPL_SIMPLE_PROPERTY_GETTER(int, MemUsageForIntegration, getMemUsageForIntegration, HkpSimulationIsland);
			IMPL_SIMPLE_PROPERTY_GETTER(int, StorageIndex, getStorageIndex, HkpSimulationIsland);
			IMPL_SIMPLE_PROPERTY_GET(int, NumConstraints, m_numConstraints, HkpSimulationIsland);
		}
	}
}
